package com.smh.aiagent.template;

import com.smh.aiagent.config.MinioProperties;
import com.smh.aiagent.model.pojo.FileInfo;
import io.minio.*;
import io.minio.messages.Bucket;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.nio.file.Files;
import java.util.List;
import java.util.UUID;

@Component
public class MinioTemplate {
    private static final Logger logger = LoggerFactory.getLogger(MinioTemplate.class);

    private final MinioClient minioClient;
    private final MinioProperties minioProperties;

    public MinioTemplate(MinioProperties minioProperties) {
        this.minioProperties = minioProperties;
        this.minioClient = MinioClient.builder()
                .endpoint(minioProperties.getEndpoint())
                .credentials(minioProperties.getAccessKey(), minioProperties.getSecretKey())
                .build();
    }

    /**
     * 初始化Bucket
     */
    public void createBucket(String bucketName) {
        try {
            boolean exists = minioClient.bucketExists(BucketExistsArgs.builder().bucket(bucketName).build());
            if (!exists) {
                minioClient.makeBucket(MakeBucketArgs.builder().bucket(bucketName).build());
            }
        } catch (Exception e) {
            logger.error("创建bucket失败: ", e);
            throw new RuntimeException("创建bucket失败", e);
        }
    }

    /**
     * 上传文件
     */
    public FileInfo uploadFile(MultipartFile file) {
        String originalFilename = file.getOriginalFilename();
        String fileName = generateFileName(originalFilename);
        try {
            PutObjectArgs objectArgs = PutObjectArgs.builder()
                    .bucket(minioProperties.getBucketName())
                    .object(fileName)
                    .stream(file.getInputStream(), file.getSize(), -1)
                    .contentType(file.getContentType())
                    .build();
            minioClient.putObject(objectArgs);

            return FileInfo.builder()
                    .fileName(fileName)
                    .originalFileName(originalFilename)
                    .bucketName(minioProperties.getBucketName())
                    .contentType(file.getContentType())
                    .fileSize(file.getSize())
                    .url(getFileUrl(fileName))
                    .build();
        } catch (Exception e) {
            logger.error("上传文件失败: ", e);
            return null;
        }
    }

    /**
     * 上传本地文件
     *
     * @param localFilePath 本地文件路径
     * @return FileInfo 文件信息
     */
    public FileInfo uploadFile(String localFilePath) {
        File file = new File(localFilePath);
        if (!file.exists()) {
            throw new RuntimeException("文件不存在: " + localFilePath);
        }

        String fileName = generateFileName(file.getName());
        try {
            String contentType = Files.probeContentType(file.toPath());
            if (!StringUtils.hasText(contentType)) {
                contentType = "application/octet-stream";
            }

            PutObjectArgs objectArgs = PutObjectArgs.builder()
                    .bucket(minioProperties.getBucketName())
                    .object(fileName)
                    .stream(new FileInputStream(file), file.length(), -1)
                    .contentType(contentType)
                    .build();
            minioClient.putObject(objectArgs);

            return FileInfo.builder()
                    .fileName(fileName)
                    .originalFileName(file.getName())
                    .bucketName(minioProperties.getBucketName())
                    .contentType(contentType)
                    .fileSize(file.length())
                    .url(getFileUrl(fileName))
                    .build();
        } catch (Exception e) {
            logger.error("上传本地文件失败: ", e);
            return null;
        }
    }

    /**
     * 上传文件流
     *
     * @param inputStream      输入流
     * @param size             文件大小
     * @param originalFilename 原始文件名
     * @param contentType      内容类型
     * @return FileInfo 文件信息
     */
    public FileInfo uploadFile(InputStream inputStream, long size, String originalFilename, String contentType) {
        String fileName = generateFileName(originalFilename);
        try {
            PutObjectArgs objectArgs = PutObjectArgs.builder()
                    .bucket(minioProperties.getBucketName())
                    .object(fileName)
                    .stream(inputStream, size, -1)
                    .contentType(contentType)
                    .build();
            minioClient.putObject(objectArgs);

            return FileInfo.builder()
                    .fileName(fileName)
                    .originalFileName(originalFilename)
                    .bucketName(minioProperties.getBucketName())
                    .contentType(contentType)
                    .fileSize(size)
                    .url(getFileUrl(fileName))
                    .build();
        } catch (Exception e) {
            logger.error("上传文件流失败: ", e);
            return null;
        }
    }

    /**
     * 下载文件
     */
    public InputStream downloadFile(String fileName) {
        try {
            return minioClient.getObject(
                    GetObjectArgs.builder()
                            .bucket(minioProperties.getBucketName())
                            .object(fileName)
                            .build());
        } catch (Exception e) {
            logger.error("下载文件失败: ", e);
            return null;
        }
    }

    /**
     * 删除文件
     */
    public void deleteFile(String fileName) {
        try {
            minioClient.removeObject(
                    RemoveObjectArgs.builder()
                            .bucket(minioProperties.getBucketName())
                            .object(fileName)
                            .build());
        } catch (Exception e) {
            logger.error("删除文件失败: ", e);
        }
    }

    /**
     * 获取文件访问URL
     */
    public String getFileUrl(String fileName) {
        return String.format("%s/%s/%s", minioProperties.getEndpoint(),
                minioProperties.getBucketName(), fileName);
    }

    /**
     * 生成文件名
     */
    private String generateFileName(String originalFilename) {
        String uuid = UUID.randomUUID().toString().replaceAll("-", "");
        String ext = getFileExtension(originalFilename);
        return String.format("%s.%s", uuid, ext);
    }

    /**
     * 获取文件扩展名
     */
    private String getFileExtension(String filename) {
        if (filename == null)
            return "";
        int lastIndexOf = filename.lastIndexOf(".");
        if (lastIndexOf == -1)
            return "";
        return filename.substring(lastIndexOf + 1);
    }

    /**
     * 获取所有bucket
     */
    public List<Bucket> getAllBuckets() {
        try {
            return minioClient.listBuckets();
        } catch (Exception e) {
            logger.error("获取bucket列表失败: ", e);
            return null;
        }
    }
}